#pragma once

#include <algorithm>
#include <cassert>
#include <vector>
#include "VectorBase.h"

#include "Containers/Optional.h"
#include "Containers/Hash.h"

template<typename DataType> class TVector;

template<typename DataType> 
class TVectorIterator
{
public:
    using value_type=DataType;
    using iterator_category=std::random_access_iterator_tag;
    using difference_type=std::ptrdiff_t;
    using pointer= DataType*;
    using reference=DataType &;

    TVectorIterator(DataType* InData)
    {
        Data = InData;
    }
    DataType& operator*() const
    {
        return *Data;
    }

    bool operator !=(const TVectorIterator& Other) const
    {
        return Data != Other.Data;
    }

    TVectorIterator& operator ++()
    {
        Data++;
        return *this;
    }

    const TVectorIterator& operator ++() const
    {
        Data++;
        return *this;
    }

    TVectorIterator& operator --()
    {
        Data--;
        return *this;
    }

    const TVectorIterator& operator --() const
    {
        Data--;
        return *this;
    }


    //return distance of iterator, std::sort will use this function
    uint64_t operator -(TVectorIterator<DataType> Other) const
    {
        return Data-Other.Data;
    }

    TVectorIterator operator -(uint64_t Distance) const
    {
        return TVectorIterator(Data-Distance);
    }

    TVectorIterator operator +(uint64_t Distance) const
    {
        return TVectorIterator(Data+Distance);
    }

    std::strong_ordering operator <=>(const TVectorIterator<DataType>& Other) const
    {
        return Data<=>Other.Data;
    }

    std::strong_ordering operator <=>(TVectorIterator<DataType> Other) 
    {
        return Data<=>Other.Data;
    }

    bool operator ==(const TVectorIterator<DataType>& Other) const
    {
        return Data==Other.Data;
    }

    bool operator ==(TVectorIterator<DataType> Other) 
    {
        return Data==Other.Data;
    }
private:
    DataType* Data = nullptr;
};

//是否需要调用无参构造函数的类型
template<typename DataType>
constexpr bool NeedConstructType_V = 
    std::is_class_v<DataType> 
    && !std::is_trivially_constructible_v<DataType>;

template<typename DataType>
concept IsNeedConstructType = NeedConstructType_V<DataType>;

//是否需要调用析构函数的类型
template<typename DataType>
constexpr bool NeedDestructType_V = 
    std::is_class_v<DataType> 
    && !std::is_trivially_destructible_v<DataType>;
    

//是否需要调用复制构造函数的类型
template<typename DataType>
constexpr bool NeedCopyConstructType_V = 
    std::is_class_v<DataType> 
    && !std::is_trivially_copy_constructible_v<DataType>;

template<typename DataType>
concept IsNeedCopyConstructType = NeedCopyConstructType_V<DataType>;


//是否需要调用移动构造函数的类型
template<typename DataType>
constexpr bool NeedMoveConstructType_V = 
    std::is_class_v<DataType> 
    && !std::is_trivially_move_constructible_v<DataType>;

template<typename DataType>
concept IsNeedMoveConstructType = NeedMoveConstructType_V<DataType>;

//是否需要调用复制赋值函数的类型
template<typename DataType>
constexpr bool NeedCopyAssignType_V = 
    std::is_class_v<DataType> 
    && !std::is_trivially_copy_assignable_v<DataType>;

//是否需要调用移动赋值函数的类型
template<typename DataType>
constexpr bool NeedMoveAssignType_V = 
    std::is_class_v<DataType> 
    && !std::is_trivially_move_assignable_v<DataType>;


//是否是基础可内存拷贝的类型,
//不能使用std::is_trivially_copyable_v,
//因为构造函数使用这个模板的类型可能会导致编译错误C2139(MSVC)
//例如
//class A
// {
//     TVector<A> AVector;
// }
//所以这里简单判断是否是基础类型
template<typename DataType>
concept IsTriviallyCopyable = 
    std::is_pointer_v<DataType>
    || std::is_enum_v<DataType>
    || std::is_arithmetic_v<DataType>
    || std::is_same_v<DataType,std::nullptr_t>
    || std::is_same_v<DataType,char>
    || std::is_same_v<DataType,wchar_t>
    || std::is_same_v<DataType,char8_t>    
    || std::is_same_v<DataType,char16_t>
    || std::is_same_v<DataType,char32_t>
    || std::is_same_v<DataType,bool>;

template<typename DataType>
class  TVector :public CVectorBase < DataType >
{
public:
    using ContainerDataType=DataType;

    TVector() {};

    TVector(std::initializer_list<DataType> InitList)
    :TVector(InitList.begin(),(uint64_t)InitList.size())
	{
	}

    TVector(const DataType* InDataSrc,uint64_t DataNum)
    {
        Reallocate(DataNum);

        for (uint64_t Index = 0; Index < DataNum; Index++)
        {
             new (this->LowLevelData + (Index)) DataType(*(InDataSrc + Index));
        }
        this->ArrayNum = DataNum;

    };

    TVector(const std::vector<DataType>& Other)
    requires (!IsTriviallyCopyable<DataType>)
    {
        Reallocate(Other.size());

        for (auto& DataItem : Other)
        {
            Add(DataItem);
        }
    }

    TVector(const std::vector<DataType>& Other)
    requires (IsTriviallyCopyable<DataType>)
    {
        Reallocate(Other.size());
        memcpy(this->LowLevelData, Other.data(), sizeof(DataType) * Other.size());
        this->ArrayNum = Other.size();
    }


    TVector(const TVector<DataType>& Other)
    requires (!IsTriviallyCopyable<DataType>)
    {
        Reallocate(Other.AllocatedNum);

        for (auto& DataItem : Other)
        {
            Add(DataItem);
        }
    }

    TVector(const TVector<DataType>& Other)
    requires (IsTriviallyCopyable<DataType>)
    {
        Reallocate(Other.AllocatedNum);
        memcpy(this->LowLevelData, Other.LowLevelData, sizeof(DataType) * Other.ArrayNum);
        this->ArrayNum = Other.ArrayNum;
    }

    TVector(TVector<DataType>&& Other)
    {
        this->LowLevelData = Other.LowLevelData;
        this->ArrayNum = Other.ArrayNum;
        this->AllocatedNum = Other.AllocatedNum;

        Other.LowLevelData = nullptr;
        Other.ArrayNum =0;
        Other.AllocatedNum = 0;
    }

    //construct from iterator range
    template<typename IteratorType>
    TVector(IteratorType Begin,IteratorType End)
    {
        Reallocate(std::distance(Begin,End));

        for (auto Iter = Begin; Iter != End; ++Iter)
        {
            Add(*Iter);
        }
    }


    TVector<DataType>& operator=(const TVector<DataType>& Other)
    {
        if(this==&Other)
        {
            return *this;
        }

        Clear(false);

        Reallocate(Other.ArrayNum);

        for (auto& DataItem : Other)
        {
            Add(DataItem);
        }

        return *this;
    }

    TVector<DataType>& operator=(std::initializer_list<DataType> InitList)
	{
        Clear(false);

        Reallocate( (uint64_t)InitList.size());

        for (uint64_t Index = 0; Index < (uint64_t)InitList.size(); Index++)
        {
            new (this->LowLevelData + (Index)) DataType(*(InitList.begin() + Index));
        }

        this->ArrayNum =  (uint64_t)InitList.size();
        return *this;
	}

    TVector<DataType>& operator=(TVector<DataType>&& Other)
    {
        if(this==&Other)
        {
            return *this;
        }

        Clear();

        this->LowLevelData = Other.LowLevelData;
        this->ArrayNum = Other.ArrayNum;
        this->AllocatedNum = Other.AllocatedNum;

        Other.LowLevelData = nullptr;
        Other.ArrayNum = 0;
        Other.AllocatedNum = 0;

        return *this;
    }


    ~TVector() {
        Clear();
    };

    bool operator==(const TVector<DataType>& Other) const
    {
        if (this->ArrayNum != Other.ArrayNum)
        {
            return false;
        }

        for (uint64_t Index = 0; Index < this->ArrayNum; Index++)
        {
            if (At(Index) != Other.At(Index))
            {
                return false;
            }
        }

        return true;
    }

    //for std::map key
    bool operator < (const TVector<DataType>& Other) const
    {
        if (this->ArrayNum != Other.ArrayNum)
        {
            return this->ArrayNum < Other.ArrayNum;
        }

        for (uint64_t Index = 0; Index < this->ArrayNum; Index++)
        {
            if (At(Index) != Other.At(Index))
            {
                return At(Index) < Other.At(Index);
            }
        }

        return false;
    }

    DataType& At(uint64_t InIndex)
    {
        assert(InIndex < this->ArrayNum);

        return *(this->LowLevelData + InIndex);
    }

    const DataType& At(uint64_t InIndex) const
    {
        assert(InIndex < this->ArrayNum);

        return *(this->LowLevelData + InIndex);
    }

    DataType& Last()
    {
        assert(this->ArrayNum > 0);

        return *(this->LowLevelData + this->ArrayNum - 1);
    }

    const DataType& Last() const
    {
        assert(this->ArrayNum > 0);

        return *(this->LowLevelData + this->ArrayNum - 1);
    }

    DataType& First()
    {
        assert(this->ArrayNum > 0);

        return *(this->LowLevelData);
    }

    const DataType& First() const
    {
        assert(this->ArrayNum > 0);

        return *(this->LowLevelData);
    }

    DataType&  operator [](uint64_t InIndex)
    {
        return At(InIndex);
    }
    const DataType& operator [](uint64_t InIndex) const
    {
        return At(InIndex);
    }

    void Reallocate(uint64_t inSize)
    {
        if (this->AllocatedNum == inSize)
        {
            return;
        }

        DataType* NewData = nullptr;

        if (inSize > 0)
        {
            NewData =reinterpret_cast<DataType*>(new uint8_t[sizeof(DataType) * inSize]);//    new DataType[inSize];
        }

        uint64_t NewDataNum = std::min(inSize, this->ArrayNum);

        MoveDataNoOverlap(NewData, this->LowLevelData, NewDataNum);

        //释放旧内存
        if (this->LowLevelData != nullptr)
        {
            delete[] (uint8_t*)this->LowLevelData;
        }

        this->LowLevelData = NewData;

        this->ArrayNum = NewDataNum;
        this->AllocatedNum = inSize;
    }

    void Reserve(uint64_t MinSize)
    {
        if (MinSize <= this->AllocatedNum)
        {
            return;
        }

        Reallocate(MinSize);

    }

    void ShrinkToFit()
    {
        Reallocate(this->ArrayNum);
    }

    void ResizeWithoutConstruct(uint64_t NewSize,bool ShrinkCapacity=true)
    {
        if(ShrinkCapacity)
        {
            ShrinkToFit(NewSize);
        }else
        {
            Reserve(NewSize);
        }

        this->ArrayNum=NewSize;        
    }

    //if extend size , will add data with default constructor 
    void Resize(uint64_t NewSize,bool ShrinkCapacity=true)
    {
        if(ShrinkCapacity)
        {
            Reallocate(NewSize);
        }else
        {
            Reserve(NewSize);
        }

        if(NewSize==this->ArrayNum)
        {
            return;
        }

        if constexpr(NeedConstructType_V<DataType>)
        {
            for(uint64_t Index=this->ArrayNum;Index<NewSize;Index++)
            {
                new (this->LowLevelData + Index) DataType();  
            }
        }

        this->ArrayNum=NewSize;
    }

    void Add(const DataType& InData)
    {
        Reserve(this->ArrayNum + 1);

        if constexpr(NeedMoveConstructType_V<DataType>)
        {
            new (this->LowLevelData + (this->ArrayNum)) DataType(std::move(InData));
        }
        else if constexpr(NeedCopyConstructType_V<DataType>)
        {
            new (this->LowLevelData + (this->ArrayNum)) DataType(InData);
        }
        else
        {
            memcpy(this->LowLevelData + this->ArrayNum, &InData, sizeof(DataType));
        }

        this->ArrayNum++;
    }

    void Add(DataType&& InData)
    {
        Reserve(this->ArrayNum + 1);

        if constexpr(NeedMoveConstructType_V<DataType>)
        {
            new (this->LowLevelData + (this->ArrayNum)) DataType(std::move(InData));
        }
        else if constexpr(NeedCopyConstructType_V<DataType>)
        {
            new (this->LowLevelData + (this->ArrayNum)) DataType(InData);
        }
        else
        {
            memcpy(this->LowLevelData + this->ArrayNum, &InData, sizeof(DataType));
        }

        this->ArrayNum++;
    }

    uint64_t AddUnique(const DataType& InData)
    {
        for(uint64_t Index=0; Index<this->ArrayNum ;Index++)
        {
            if(At(Index)==InData)
            {
                return Index;
            }
        }

        Add(InData);

        return this->ArrayNum-1;
    }

    void AddUnique(DataType&& InDatas)
    {
        for(uint64_t Index=0; Index<this->ArrayNum ;Index++)
        {
            if(At(Index)==InDatas)
            {
                return;
            }
        }

        Add(std::move(InDatas));
    }

    DataType& Emplace()
    {
        Reserve(this->ArrayNum + 1);

        if constexpr(NeedConstructType_V<DataType>)
        {
            new (this->LowLevelData + (this->ArrayNum)) DataType();
        }

        this->ArrayNum++;

        return *(this->LowLevelData+this->ArrayNum-1);
    }

    void Insert(uint64_t InIndex, const DataType& InData)
    {
        assert(InIndex <= this->ArrayNum);

        if (InIndex == this->ArrayNum)
        {
            Add(InData);
            return;
        }

        Reserve(this->ArrayNum + 1);

        //向后移动数据
        if constexpr(NeedMoveConstructType_V<DataType>)
        {
            for (uint64_t Index = this->ArrayNum; Index > InIndex; Index--)
            {
                new (this->LowLevelData + Index) DataType(std::move(*(this->LowLevelData + Index - 1)));
            }
        }
        else if constexpr(NeedCopyConstructType_V<DataType>)
        {
            for (uint64_t Index = this->ArrayNum; Index > InIndex; Index--)
            {
                new (this->LowLevelData + Index) DataType(*(this->LowLevelData + Index - 1));
            }
        }
        else
        {
            memmove(this->LowLevelData + InIndex + 1, this->LowLevelData + InIndex, sizeof(DataType) * (this->ArrayNum - InIndex));
        }

        //插入新数据
        if constexpr (NeedMoveAssignType_V<DataType>)
        {
            *(this->LowLevelData + InIndex) = std::move(InData);
        }
        else if constexpr(NeedCopyAssignType_V<DataType>)
        {
            *(this->LowLevelData + InIndex) = InData;
        }
        else if constexpr (NeedMoveConstructType_V<DataType>)
        {
            if constexpr(NeedDestructType_V<DataType>)
            {
                (this->LowLevelData + InIndex)->DataType::~DataType();
            }

            new (this->LowLevelData + InIndex) DataType(std::move(InData));
        }
        else if constexpr(NeedCopyConstructType_V<DataType>)
        {
            if constexpr(NeedDestructType_V<DataType>)
            {
                (this->LowLevelData + InIndex)->DataType::~DataType();
            }

            new (this->LowLevelData + InIndex) DataType(InData);
        }
        else
        {
            memcpy(this->LowLevelData + InIndex, &InData, sizeof(DataType));
        }


        this->ArrayNum++;
    }

    void Move(uint64_t InFromIndex,uint64_t InToIndex)
    {
        assert(InFromIndex < this->ArrayNum);
        assert(InToIndex < this->ArrayNum);

        if(InFromIndex==InToIndex)
        {
            return;
        }

        DataType Temp=std::move(At(InFromIndex));

        if(InFromIndex<InToIndex)
        {
            for(uint64_t Index=InFromIndex;Index<InToIndex;Index++)
            {
                At(Index)=std::move(At(Index+1));
            }
        }
        else
        {
            for(uint64_t Index=InFromIndex;Index>InToIndex;Index--)
            {
                At(Index)=std::move(At(Index-1));
            }
        }

        At(InToIndex)=std::move(Temp);
    }

    void Append(const TVector<DataType>& Other)
    {
        Reserve(this->ArrayNum + Other.ArrayNum);

        if constexpr(NeedMoveConstructType_V<DataType>)
        {
            for (uint64_t Index = 0; Index < Other.ArrayNum; Index++)
            {
                new (this->LowLevelData + (this->ArrayNum + Index)) DataType(std::move(Other[Index]));
            }
        }
        else if constexpr(NeedCopyConstructType_V<DataType>)
        {
            for (uint64_t Index = 0; Index < Other.ArrayNum; Index++)
            {
                new (this->LowLevelData + (this->ArrayNum + Index)) DataType(Other[Index]);
            }
        }
        else
        {
            memcpy(this->LowLevelData + this->ArrayNum, Other.LowLevelData, sizeof(DataType) * Other.ArrayNum);
        }

        this->ArrayNum+= Other.ArrayNum;
    }

    void RemoveAt(uint64_t InIndex,bool ShrinkCapacity=true)
    {
        Remove(InIndex,1,ShrinkCapacity);
    }

    void Remove(uint64_t InIndex,uint64_t InCount ,bool ShrinkCapacity=true)
    {
        assert(InIndex < this->ArrayNum);

        uint64_t Count=InCount<(this->ArrayNum-InIndex) ? InCount : (this->ArrayNum-InIndex); 

        //析构被移除的数据
        if constexpr(NeedDestructType_V<DataType>)
        {
            for(uint64_t Index=0;Index<Count; Index++)
            {
                (this->LowLevelData + InIndex + Index)->DataType::~DataType();
            }
        }

        if constexpr(NeedMoveConstructType_V<DataType>)
        {
            //向前移动之后的数据
            for(uint64_t Index=InIndex;Index<this->ArrayNum-Count;Index++)
            {
                new (this->LowLevelData + Index) DataType(std::move(*(this->LowLevelData + Index + Count)));
            }

        }
        else if constexpr(NeedCopyConstructType_V<DataType>)
        {
            //向前移动之后的数据
            for(uint64_t Index=InIndex;Index<this->ArrayNum-Count;Index++)
            {
                new (this->LowLevelData + Index) DataType(*(this->LowLevelData + Index + Count));
            }
        }
        else
        {
            //向前移动之后的数据
            memmove(this->LowLevelData + InIndex, this->LowLevelData + InIndex + Count, sizeof(DataType) * (this->ArrayNum - InIndex - Count));
        }

        //析构多余的数据
        if constexpr(NeedDestructType_V<DataType>)
        {
            for(uint64_t Index=0;Index<Count;Index++)
            {
                (this->LowLevelData + this->ArrayNum -1 - Index)->DataType::~DataType();
            }
        }
    
        this->ArrayNum=this->ArrayNum-Count;

        if(ShrinkCapacity)
        {
            ShrinkToFit();
        }
    }

    //remove item that Predicate return true
    void RemoveBy(const std::function<bool(const DataType&)>& Predicate,bool ShrinkCapacity=true)
    {
        for (uint64_t Index = 0; Index < this->ArrayNum; Index++)
        {
            if(Predicate(At(Index)))
            {
                RemoveAt(Index,false);
                Index--;
            }
        }

        if(ShrinkCapacity)
        {
            ShrinkToFit();
        }
    }

    //remove the last item
    void RemoveLast(bool ShrinkCapacity=true)
    {
        assert(this->ArrayNum > 0);

        if constexpr(NeedDestructType_V<DataType>)
        {
            (this->LowLevelData + this->ArrayNum -1)->DataType::~DataType();
        }

        this->ArrayNum--;

        if(ShrinkCapacity)
        {
            ShrinkToFit();
        }
    }

    //remove item at {InIndex} and after it
    void RemoveAndAfter(uint64_t InIndex,bool ShrinkCapacity=true)
    {
        Remove(InIndex,
            this->ArrayNum-InIndex
            ,ShrinkCapacity);
    }

    void RemoveAfter(uint64_t InIndex,bool ShrinkCapacity=true)
    {
        Remove(InIndex+1,
            this->ArrayNum-InIndex-1
            ,ShrinkCapacity);
    }

    bool Contains(const DataType& InData) const
    {
        for(uint64_t ItemIndex=0;ItemIndex< this->ArrayNum;ItemIndex++)
        {
            if(At(ItemIndex)==InData)
            {
                return true;
            }
        }
        return false;
    }

    void Remove(const DataType& InData,bool ShrinkCapacity=true)
    {
        //find index
        uint64_t ItemIndex=0;
        for(;ItemIndex< this->ArrayNum;ItemIndex++)
        {
            if(At(ItemIndex)==InData)
            {
                break;
            }
        }

        if(ItemIndex== this->ArrayNum)
        {
            //cant find 
            return;
        }

        RemoveAt(ItemIndex,ShrinkCapacity);
    }  

    void Swap(uint64_t InIndexA,uint64_t InIndexB)
    {
        assert(InIndexA < this->ArrayNum);
        assert(InIndexB < this->ArrayNum);

        std::swap(*(this->LowLevelData + InIndexA), *(this->LowLevelData + InIndexB));
    }

    //return all item that  the predicate return true
    TVector<DataType> Filter(const std::function<bool(const DataType&)>& Predicate)
    {
        TVector<DataType> NewVector;
        NewVector.Reserve(this->ArrayNum);

        for(uint64_t ItemIndex=0;ItemIndex< this->ArrayNum;ItemIndex++)
        {
            if(Predicate(At(ItemIndex)))
            {
                NewVector.Add(At(ItemIndex));
            }
        }

        return NewVector;
    }


    TOptional<uint64_t> Find(const DataType& InData,bool FromEnd=false) const
    {
        if(FromEnd)
        {
            for (uint64_t Index = this->ArrayNum-1; Index >=0 && Index!=((uint64_t)0-1); Index--)
            {
                if(At(Index)==InData)
                {
                    return Index;
                }
            }
        }
        else
        {
            for (uint64_t Index = 0; Index < this->ArrayNum; Index++)
            {
                if(At(Index)==InData)
                {
                    return Index;
                }
            }
        }
        return TOptional<uint64_t>();
    }

    //find or add item
    uint64_t FindOrAdd(const DataType& InData)
    {
        TOptional<uint64_t> Index=Find(InData);
        if(Index.HasValue())
        {
            return Index.GetValue();
        }
        else
        {
            Add(InData);
            return this->ArrayNum-1;
        }
    }

    template<typename FunctorType> 
    TOptional<uint64_t> FindBy(const FunctorType& InFunctor) const    
    {
        for (uint64_t Index = this->ArrayNum-1; Index >=0 && Index!=((uint64_t)0-1); Index--)
        {
            if(InFunctor(At(Index)))
            {
                return Index;
            }
        }

        return TOptional<uint64_t>();
    }

    TOptional<uint64_t> IndexOf(const DataType& InData) const
    {
        for (uint64_t Index = 0; Index < this->ArrayNum; Index++)
        {
            if(At(Index)==InData)
            {
                return Index;
            }
        }
        return TOptional<uint64_t>();
    }

    //pop the last item
    DataType Pop(bool ShrinkCapacity=true)
    {
         assert( this->ArrayNum >0);

        DataType Item =DataType(std::move(At( this->ArrayNum-1)));

        //deconstruct last one
        if constexpr(NeedDestructType_V<DataType>)
        {
            (this->LowLevelData + this->ArrayNum -1)->DataType::~DataType();
        }

        this->ArrayNum--;

        if(ShrinkCapacity)
        {
            ShrinkToFit();
        }

        return Item;       

    }

    void RemoveFirst(const DataType& InData,bool ShrinkCapacity=true)
    {
        for (int32_t Index = 0; Index < this->ArrayNum; Index++)
        {
            if(At(Index)==InData)
            {
                Remove(Index,ShrinkCapacity);
                return;
            }
        }
    }


    void Clear(bool ShrinkCapacity=true) 
    {
        if (this->LowLevelData != nullptr)
        {
            //deconstruct items
            if constexpr(NeedDestructType_V<DataType>)
            {
                for (uint64_t Index = 0; Index < this->ArrayNum; Index++)
                {
                    (this->LowLevelData + Index)->DataType::~DataType();
                }
            }
            this->ArrayNum = 0;

            if(ShrinkCapacity)
            {
                delete[](uint8_t*) this->LowLevelData;
                this->LowLevelData = nullptr;
                this-> AllocatedNum = 0;
            }
        }
    }

    template<typename... ArgsType>
    void Emplace(ArgsType&&... Args)
    {
        Reserve(this->ArrayNum + 1);

        new (this->LowLevelData + (this->ArrayNum)) DataType(std::forward<ArgsType>(Args)...);
        
        this->ArrayNum++;
    }

    //get sub vector [InStartIndex,InEndIndex)
    TVector<DataType> Slice(uint64_t InStartIndex,uint64_t InEndIndex) const
    {
        assert(InStartIndex < this->ArrayNum);
        assert(InEndIndex <= this->ArrayNum);

        TVector<DataType> NewVector;
        NewVector.Reallocate(InEndIndex-InStartIndex);

        for(uint64_t Index=InStartIndex;Index<InEndIndex;Index++)
        {
            NewVector.Add(At(Index));
        }

        return NewVector;
    }

    DataType* Data() const 
    {
        return this->LowLevelData;
    }


    TVectorIterator<DataType> begin() const
    {
        return TVectorIterator<DataType>(this->LowLevelData);
    }

    TVectorIterator<DataType> end() const
    {
        return TVectorIterator<DataType>(this->LowLevelData+ this->ArrayNum);
    }
    std::reverse_iterator<TVectorIterator<DataType>> rbegin() const
    {
        return std::reverse_iterator(end());
    }

    std::reverse_iterator<TVectorIterator<DataType>> rend() const
    {
        return std::reverse_iterator(begin());
    }

    void Reverse() 
    {
        std::reverse(begin(),end());
    }

    //sort by functor
    //for example:
    //  TVector<int> IntVector={1,2,3};
    //  IntVector.Sort([](int A,int B){return A<B;});
    //the result is {1,2,3}
    template<typename FunctorType>
    void Sort(const FunctorType& InFunctor)
    {
        std::sort(begin(),end(),InFunctor);
    }

    void * GetDataPtr(uint64_t InIndex)
    {
        return this->LowLevelData+InIndex;
    };
    const void * GetDataPtr(uint64_t InIndex)const
    {
        return this->LowLevelData+InIndex;
    }

    // make convertibal to vk::arrayproxy
    DataType* data() const 
    {
        return this->LowLevelData;
    }
    
    // make convertibal to vk::arrayproxy
    uint64_t size() const
    {
        return this->ArrayNum;
    }


    uint64_t GetHashCode() const
    {
        uint64_t HashCode=this->ArrayNum;
        uint8_t CalculateNum=std::min((uint64_t)8,this->ArrayNum);
        for (uint64_t Index = 0; Index < CalculateNum; Index++)
        {
            WH::HashCombine(HashCode,WH::GetHashCode(*(this->LowLevelData+ Index)));
        }
        return HashCode;
    }

public:

    static TVector<DataType> CreateFilledVector(uint64_t InVectorSize)
    {
        TVector<DataType> Vector;
        Vector.Reallocate(InVectorSize);
        
        if constexpr(NeedConstructType_V<DataType>)
        {
            for (uint64_t Index = 0; Index < InVectorSize; Index++)
            {
                new (Vector.LowLevelData + Index) DataType();
            }
        }

        Vector.ArrayNum = InVectorSize;

        return Vector;
    }

    //使用移动构造函数移动数据,内存区域不重叠
    static void MoveDataNoOverlap(
        DataType* InDesMemory
        ,DataType* InSrcMemory
        ,uint64_t Num) 
    requires (IsNeedMoveConstructType<DataType>)
    {
        for(uint64_t Index=0;Index<Num;Index++)
        {
            new (InDesMemory + Index) DataType(std::move(*(DataType*)(InSrcMemory + Index)));
        }
    }

    //使用复制构造函数移动数据,内存区域不重叠
    static void MoveDataNoOverlap(
        DataType* InDesMemory
        ,DataType* InSrcMemory
        ,uint64_t Num)
    requires (!IsNeedMoveConstructType<DataType> && IsNeedCopyConstructType<DataType>)
    {
        for(uint64_t Index=0;Index<Num;Index++)
        {
            new (InDesMemory + Index) DataType(*(DataType*)(InSrcMemory + Index));
        }

        if constexpr(NeedDestructType_V<DataType>)
        {
            for(uint64_t Index=0;Index<Num;Index++)
            {
                (InSrcMemory + Index)->DataType::~DataType();
            }
        }
    }

    //用复制内存的方法复制数据,内存区域不重叠
    static void MoveDataNoOverlap(
        DataType* InDesMemory
        ,DataType* InSrcMemory
        ,uint64_t Num)
    requires (!IsNeedMoveConstructType<DataType> && !IsNeedCopyConstructType<DataType>)
    {
        std::memcpy(InDesMemory,InSrcMemory,sizeof(DataType)*Num);
    }
};


template<typename T>
constexpr bool Is_TVector_V=false;

template<typename... T>
constexpr bool Is_TVector_V<TVector<T...>> = true;


template <typename  T>
concept IsTVector =Is_TVector_V<T>;// std::same_as<T,TVector<T::ContainerDataType>>;
